I'm only here tonight because of you. You are the reason I am. You are all my reason.
A beautiful mind.(2001)
單一職責的名稱其實有點混淆,有些人會誤解為一個類別只應做一件事情,但這個職責其實包含了更大的概念,是指一個類別應該只因為一個理由而變動,也能是說只對一個商業邏輯負責
在任何的組織內都會有許多潛在的需求變動可能,可能是不同開發者、主管、部門、新需求等等,如果更動的邏輯在共用模組的話,可能會引發危險且不易察覺的錯誤
在一間保險公司內,儲存著客戶的年齡、保單、風險評估、經濟狀況等資料,有風險評估部、會計部都會呼叫 getPrice
,今天風險評估部發現得 covid
的人很多,要去調整風險權重,就給工程部一個任務,把 covid
的相關權重提高 15% ,此時其他部門完全不知情,就在程式部署後會出現以下問題
會計部從下次收費開始,開始跟用戶收取超過保單契約的金額,有天被用戶發現,提告,處理很麻煩的法律程序跟會計清算
對的,don't repeat youself 的概念不僅是減少相同代碼,還要再業務邏輯上詳加思考,隨意的共用程式也會帶來災難
那這兩者會差在哪裡呢?
這兩者的需求,會依不同的時空背景而有不同程度的變化,在這之間共用邏輯往往會有無法預料不可思議的效果
如你所見,一點的改變會影響其他依賴於這個更動模組,並可能造成不同結果,的確這個邏輯應該被單元測試所偵測到,但更重要的是,開發者期望一個模組負責一個業務邏輯,解法其實很簡單,為變化頻率不同的商業邏輯規劃不同的模組
The naming is actually confusing, this principle doesn't mean one scope should focus on one task, it means one scope/ module should be responsible for one author, or you can call one owner of business logic.
In any organization, there are many potential change point, could be different author, manager, department, new demand, when their logic will change a common usage module, it could be dangerous and might cause huge impact
Let's take an example, in an Insurance company, stored custom information like age, risk evaluate, financial state ...etc, and there are risk evaluate dept and accounting dept, both of they rely on function getPrice
, some day risk evaluate dept found out the amount of covid
positive is increasing, effect on risk weight, so they sent a task to IT dept, to increase the covid
relate weight up to 15%, without inform other dept, what will happen is
Account dept will charge extra amount from next time, some day a custom found out, and the company is facing court and annoying account check
the concept of don't repeat yourself
is not just reduce the redundancy code, it require judgment on business logic, reuse everything also cause disaster
What is the difference between those?
Those needed will change base on time and reality situation, reuse between those dept will facing unexpected result
As you can see, the change from a point affects the result of others logic relying on this module as well. You might think well this should be detect by unit test, of course it should, but the most important thing is developer should expect one module is used for different business logic, the solution is simple, write different module for different author